-
Notifications
You must be signed in to change notification settings - Fork 112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ndk: Requre all off-thread dyn Fn*
callback types to implement Send
#455
Conversation
a0a6b17
to
ac9bc7b
Compare
@spencercw since you've been active around callbacks and seem to be using this crate, would you mind helping me out reviewing this and other PRs? I don't like "forcing" my own work into the codebase without at least one extra pair of eyes. I've also been wondering why the NDK is mixing both |
Looks like a reasonable change. I'm not actively using this right now (changed jobs), but don't mind being an extra pair of eyes from time to time.
This does seem to be a little superfluous. I guess from an API point of view it means the API user doesn't need to box the callback themselves, but would be nice to be consistent across the codebase.
Tricky. I think this is probably not necessary, but it depends on the underlying NDK API. For example, |
Thanks! That's unfortunate but I have quite a bunch of PRs open now. @rib appears to be inactive because of the newyears' holidays so I'll wait for that.
I thought so too at first, until it hit me: fat pointers. The pointer coming from a let foo: Box<dyn Fn() -> u32> = Box::new(|| 1337);
let raw = dbg!(Box::into_raw(foo));
dbg!(std::mem::size_of_val(&raw)); Gives:
(Note that nothing is captured, so there's no data associated with the So we'll need to box twice if we wish to pass an
Yeah I've been giving this some thought:
Either way, deregistering callbacks or having an explicit comment that the Then secondly I've been thinking about a general lack of when and where callbacks are called, and what functions/objects/pointers are thread-safe, but that's for another time :) |
Made an attempt to request some clarifications in https://issuetracker.google.com/issues/318944941. Notice that it may be terrible for us to take an Likewise I think that Thoughts? |
I think |
@spencercw I ended up opening a new issue #464 to once again go over all callbacks and document their (lack of) standardization, so that we have a guideline how to build our callbacks going forward. On the topic of |
ac9bc7b
to
d6a3738
Compare
In all these cases the NDK either documents or implements the callback to be invoked from a single, separate thread. For this to be allowed by Rust thread safety, the closures and their (moved) contents are effectively "moved" to a different thread (`Send`) but not accessed concurrently (`Sync`), but the type definitions were never requiring this marker trait which could lead to undefined/invalid behaviour. In addition some `Box`ed callbacks may have been dropped before a new callback is passed to the NDK, leading to a possible race condition. By storing the new callback _after_ registering it with the NDK, the previous callback is now dropped later to ensure such race conditions no longer happen (assuming AOSP callback invocations are properly synchronized with the setters). Multiple requests have been filed to solidify this "behavioural contract" in the documentation where not done so yet: https://issuetracker.google.com/issues/300602767#comment12 https://issuetracker.google.com/issues/318944941
d6a3738
to
c9fc220
Compare
Fixes #454
In all these cases the NDK either documents or implements the callback to be invoked from a single, separate thread. For this to be allowed by Rust thread safety, the closures and their (moved) contents are effectively "moved" to a different thread (
Send
) but not accessed concurrently (Sync
), but the type definitions were never requiring this marker trait which could lead to undefined/invalid behaviour.In addition some
Box
ed callbacks may have been dropped before a new callback is passed to the NDK, leading to a possible race condition. By storing the new callback after registering it with the NDK, the previous callback is now dropped later to ensure such race conditions no longer happen (assuming AOSP callback invocations are properly synchronized with the setters).A request has been filed to solidify this "behavioural contract" in the documentation where not done so yet: https://issuetracker.google.com/issues/300602767#comment12